home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / lpd / RCS / printjob.c,v < prev    next >
Encoding:
Text File  |  1992-05-17  |  34.9 KB  |  1,652 lines

  1. head     1.5;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.5
  10. date     89.07.14.08.47.15;  author ouster;  state Exp;
  11. branches ;
  12. next     1.4;
  13.  
  14. 1.4
  15. date     89.06.12.16.36.02;  author brent;  state Exp;
  16. branches ;
  17. next     1.3;
  18.  
  19. 1.3
  20. date     89.06.05.12.08.47;  author brent;  state Exp;
  21. branches ;
  22. next     1.2;
  23.  
  24. 1.2
  25. date     89.01.11.08.50.56;  author rab;  state Exp;
  26. branches ;
  27. next     1.1;
  28.  
  29. 1.1
  30. date     88.11.23.10.34.05;  author rab;  state Exp;
  31. branches ;
  32. next     ;
  33.  
  34.  
  35. desc
  36. @@
  37.  
  38.  
  39. 1.5
  40. log
  41. @Re-enable "xs":  needed for new tty driver.
  42. @
  43. text
  44. @/*
  45.  * Copyright (c) 1983 Regents of the University of California.
  46.  * All rights reserved.
  47.  *
  48.  * Redistribution and use in source and binary forms are permitted
  49.  * provided that this notice is preserved and that due credit is given
  50.  * to the University of California at Berkeley. The name of the University
  51.  * may not be used to endorse or promote products derived from this
  52.  * software without specific prior written permission. This software
  53.  * is provided ``as is'' without express or implied warranty.
  54.  */
  55.  
  56. #ifndef lint
  57. static char sccsid[] = "@@(#)printjob.c    5.5 (Berkeley) 5/5/88";
  58. #endif /* not lint */
  59.  
  60. /*
  61.  * printjob -- print jobs in the queue.
  62.  *
  63.  *    NOTE: the lock file is used to pass information to lpq and lprm.
  64.  *    it does not need to be removed because file locks are dynamic.
  65.  */
  66.  
  67. #include "lp.h"
  68.  
  69. #ifdef sprite
  70. #include <proc.h>
  71. #include <fs.h>
  72. #endif
  73.  
  74. #define DORETURN    0    /* absorb fork error */
  75. #define DOABORT        1    /* abort if dofork fails */
  76.  
  77. /*
  78.  * Error tokens
  79.  */
  80. #define REPRINT        (-2)
  81. #define ERROR        (-1)
  82. #define    OK        0
  83. #define    FATALERR    1
  84. #define    NOACCT        2
  85. #define    FILTERERR    3
  86. #define    ACCESS        4
  87.  
  88. char    title[80];        /* ``pr'' title */
  89. FILE    *cfp;            /* control file */
  90. int    pfd;            /* printer file descriptor */
  91. int    ofd;            /* output filter file descriptor */
  92. int    lfd;            /* lock file descriptor */
  93. int    pid;            /* pid of lpd process */
  94. int    prchild;        /* id of pr process */
  95. int    child;            /* id of any filters */
  96. int    ofilter;        /* id of output filter, if any */
  97. int    tof;            /* true if at top of form */
  98. int    remote;            /* true if sending files to remote */
  99. dev_t    fdev;            /* device of file pointed to by symlink */
  100. ino_t    fino;            /* inode of file pointed to by symlink */
  101.  
  102. char    fromhost[32];        /* user's host machine */
  103. char    logname[32];        /* user's login name */
  104. char    jobname[100];        /* job or file name */
  105. char    class[32];        /* classification field */
  106. char    width[10] = "-w";    /* page width in characters */
  107. char    length[10] = "-l";    /* page length in lines */
  108. char    pxwidth[10] = "-x";    /* page width in pixels */
  109. char    pxlength[10] = "-y";    /* page length in pixels */
  110. char    indent[10] = "-i0";    /* indentation size in characters */
  111. char    tempfile[] = "errsXXXXXX"; /* file name for filter output */
  112. extern  int debug;
  113.  
  114. printjob()
  115. {
  116.     struct stat stb;
  117.     register struct queue *q, **qp;
  118.     struct queue **queue;
  119.     register int i, nitems;
  120.     long pidoff;
  121.     int count = 0;
  122.     extern int abortpr();
  123.  
  124.     init();                    /* set up capabilities */
  125.     (void) write(1, "", 1);            /* ack that daemon is started */
  126.     /*
  127.      * Make sure the spool directory exists.
  128.      */
  129.     if (stat(SD, &stb) < 0) {
  130.         mkdir(SD, 0775);
  131.     }
  132.     (void) close(2);            /* set up log file */
  133.     if (open(LF, O_CREAT|O_WRONLY|O_APPEND, 0664) < 0) {
  134.         syslog(LOG_ERR, "%s: %m", LF);
  135.         (void) open("/dev/null", O_WRONLY);
  136.     }
  137.     setgid(getegid());
  138.     pid = getpid();                /* for use with lprm */
  139.     setpgrp(0, pid);
  140.     signal(SIGHUP, abortpr);
  141.     signal(SIGINT, abortpr);
  142.     signal(SIGQUIT, abortpr);
  143.     signal(SIGTERM, abortpr);
  144.  
  145.     (void) mktemp(tempfile);
  146.  
  147.     /*
  148.      * uses short form file names
  149.      */
  150.     if (chdir(SD) < 0) {
  151.     }
  152.     if (stat(LO, &stb) == 0 && (stb.st_mode & 0100))
  153.         exit(0);        /* printing disabled */
  154.     lfd = open(LO, O_RDWR|O_CREAT, 0644);
  155.     if (lfd < 0) {
  156.         syslog(LOG_ERR, "%s: %s: %m", printer, LO);
  157.         exit(1);
  158.     }
  159.     if (flock(lfd, LOCK_EX|LOCK_NB) < 0) {
  160.         if (errno == EWOULDBLOCK) {    /* active deamon present */
  161. #if 1
  162.             char buf[0x100];
  163.             int xpid;
  164.  
  165.             read(lfd, buf, sizeof(buf));
  166.             xpid = atoi(buf);
  167.             if (kill(xpid, 0) != 0) {
  168.             syslog(LOG_ERR, "Lock error, pid 0x%x", xpid);
  169.  
  170.             ((void (*)()) 0) ();    /* force a seg viol */
  171.             abort();
  172.             }
  173. #endif
  174.             exit(0);
  175.         }
  176.         syslog(LOG_ERR, "%s: %s: %m", printer, LO);
  177.         exit(1);
  178.     }
  179.     ftruncate(lfd, 0);
  180.     /*
  181.      * write process id for others to know
  182.      */
  183.     sprintf(line, "%u\n", pid);
  184.     pidoff = i = strlen(line);
  185.     if (write(lfd, line, i) != i) {
  186.         syslog(LOG_ERR, "%s: %s: %m", printer, LO);
  187.         exit(1);
  188.     }
  189.     /*
  190.      * search the spool directory for work and sort by queue order.
  191.      */
  192.     if ((nitems = getq(&queue)) < 0) {
  193.         syslog(LOG_ERR, "%s: can't scan %s", printer, SD);
  194.         exit(1);
  195.     }
  196.     if (nitems == 0)        /* no work to do */
  197.         exit(0);
  198.     if (stb.st_mode & 01) {        /* reset queue flag */
  199.         if (fchmod(lfd, stb.st_mode & 0776) < 0)
  200.             syslog(LOG_ERR, "%s: %s: %m", printer, LO);
  201.     }
  202.     openpr();            /* open printer or remote */
  203. again:
  204.     /*
  205.      * we found something to do now do it --
  206.      *    write the name of the current control file into the lock file
  207.      *    so the spool queue program can tell what we're working on
  208.      */
  209.     for (qp = queue; nitems--; free((char *) q)) {
  210.         q = *qp++;
  211.         if (stat(q->q_name, &stb) < 0)
  212.             continue;
  213.     restart:
  214.         (void) lseek(lfd, pidoff, 0);
  215.         (void) sprintf(line, "%s\n", q->q_name);
  216.         i = strlen(line);
  217.         if (write(lfd, line, i) != i)
  218.             syslog(LOG_ERR, "%s: %s: %m", printer, LO);
  219.         if (!remote)
  220.             i = printit(q->q_name);
  221.         else
  222.             i = sendit(q->q_name);
  223.         /*
  224.          * Check to see if we are supposed to stop printing or
  225.          * if we are to rebuild the queue.
  226.          */
  227.         if (fstat(lfd, &stb) == 0) {
  228.             /* stop printing before starting next job? */
  229.             if (stb.st_mode & 0100)
  230.                 goto done;
  231.             /* rebuild queue (after lpc topq) */
  232.             if (stb.st_mode & 01) {
  233.                 for (free((char *) q); nitems--; free((char *) q))
  234.                     q = *qp++;
  235.                 if (fchmod(lfd, stb.st_mode & 0776) < 0)
  236.                     syslog(LOG_WARNING, "%s: %s: %m",
  237.                         printer, LO);
  238.                 break;
  239.             }
  240.         }
  241.         if (i == OK)        /* file ok and printed */
  242.             count++;
  243.         else if (i == REPRINT) { /* try reprinting the job */
  244.             syslog(LOG_INFO, "restarting %s", printer);
  245.             if (ofilter > 0) {
  246.                 kill(ofilter, SIGCONT);    /* to be sure */
  247.                 (void) close(ofd);
  248.                 while ((i = wait(0)) > 0 && i != ofilter)
  249.                     ;
  250.                 ofilter = 0;
  251.             }
  252.             (void) close(pfd);    /* close printer */
  253.             if (ftruncate(lfd, pidoff) < 0)
  254.                 syslog(LOG_WARNING, "%s: %s: %m", printer, LO);
  255.             openpr();        /* try to reopen printer */
  256.             goto restart;
  257.         }
  258.     }
  259.     free((char *) queue);
  260.     /*
  261.      * search the spool directory for more work.
  262.      */
  263.     if ((nitems = getq(&queue)) < 0) {
  264.         syslog(LOG_ERR, "%s: can't scan %s", printer, SD);
  265.         exit(1);
  266.     }
  267.     if (nitems == 0) {        /* no more work to do */
  268.     done:
  269.         if (count > 0) {    /* Files actually printed */
  270.             if (!SF && !tof)
  271.                 (void) write(ofd, FF, strlen(FF));
  272.             if (TR != NULL)        /* output trailer */
  273.                 (void) write(ofd, TR, strlen(TR));
  274.         }
  275.         (void) unlink(tempfile);
  276.         exit(0);
  277.     }
  278.     goto again;
  279. }
  280.  
  281. char    fonts[4][50];    /* fonts for troff */
  282.  
  283. char ifonts[4][18] = {
  284.     "/usr/lib/vfont/R",
  285.     "/usr/lib/vfont/I",
  286.     "/usr/lib/vfont/B",
  287.     "/usr/lib/vfont/S"
  288. };
  289.  
  290. /*
  291.  * The remaining part is the reading of the control file (cf)
  292.  * and performing the various actions.
  293.  */
  294. printit(file)
  295.     char *file;
  296. {
  297.     register int i;
  298.     char *cp;
  299.     int bombed = OK;
  300.  
  301.     /*
  302.      * open control file; ignore if no longer there.
  303.      */
  304.     if ((cfp = fopen(file, "r")) == NULL) {
  305.         syslog(LOG_INFO, "%s: %s: %m", printer, file);
  306.         return(OK);
  307.     }
  308.     /*
  309.      * Reset troff fonts.
  310.      */
  311.     for (i = 0; i < 4; i++)
  312.         strcpy(fonts[i], ifonts[i]);
  313.     strcpy(width+2, "0");
  314.     strcpy(indent+2, "0");
  315.  
  316.     /*
  317.      *      read the control file for work to do
  318.      *
  319.      *      file format -- first character in the line is a command
  320.      *      rest of the line is the argument.
  321.      *      valid commands are:
  322.      *
  323.      *        S -- "stat info" for symbolic link protection
  324.      *        J -- "job name" on banner page
  325.      *        C -- "class name" on banner page
  326.      *              L -- "literal" user's name to print on banner
  327.      *        T -- "title" for pr
  328.      *        H -- "host name" of machine where lpr was done
  329.      *              P -- "person" user's login name
  330.      *              I -- "indent" amount to indent output
  331.      *              f -- "file name" name of text file to print
  332.      *        l -- "file name" text file with control chars
  333.      *        p -- "file name" text file to print with pr(1)
  334.      *        t -- "file name" troff(1) file to print
  335.      *        n -- "file name" ditroff(1) file to print
  336.      *        d -- "file name" dvi file to print
  337.      *        g -- "file name" plot(1G) file to print
  338.      *        v -- "file name" plain raster file to print
  339.      *        c -- "file name" cifplot file to print
  340.      *        1 -- "R font file" for troff
  341.      *        2 -- "I font file" for troff
  342.      *        3 -- "B font file" for troff
  343.      *        4 -- "S font file" for troff
  344.      *        N -- "name" of file (used by lpq)
  345.      *              U -- "unlink" name of file to remove
  346.      *                    (after we print it. (Pass 2 only)).
  347.      *        M -- "mail" to user when done printing
  348.      *
  349.      *      getline reads a line and expands tabs to blanks
  350.      */
  351.  
  352.     /* pass 1 */
  353.  
  354.     while (getline(cfp)) {
  355.         switch (line[0]) {
  356.         case 'H':
  357.             strcpy(fromhost, line+1);
  358.             if (class[0] == '\0')
  359.                 strncpy(class, line+1, sizeof(class)-1);
  360.             continue;
  361.  
  362.         case 'P':
  363.             strncpy(logname, line+1, sizeof(logname)-1);
  364.             if (RS) {            /* restricted */
  365.                 if (getpwnam(logname) == (struct passwd *)0) {
  366.                     bombed = NOACCT;
  367.                     sendmail(line+1, bombed);
  368.                     goto pass2;
  369.                 }
  370.             }
  371.             continue;
  372.  
  373.         case 'S':
  374.             cp = line+1;
  375.             i = 0;
  376.             while (*cp >= '0' && *cp <= '9')
  377.                 i = i * 10 + (*cp++ - '0');
  378.             fdev = i;
  379.             cp++;
  380.             i = 0;
  381.             while (*cp >= '0' && *cp <= '9')
  382.                 i = i * 10 + (*cp++ - '0');
  383.             fino = i;
  384.             continue;
  385.  
  386.         case 'J':
  387.             if (line[1] != '\0')
  388.                 strncpy(jobname, line+1, sizeof(jobname)-1);
  389.             else
  390.                 strcpy(jobname, " ");
  391.             continue;
  392.  
  393.         case 'C':
  394.             if (line[1] != '\0')
  395.                 strncpy(class, line+1, sizeof(class)-1);
  396.             else if (class[0] == '\0')
  397.                 gethostname(class, sizeof(class));
  398.             continue;
  399.  
  400.         case 'T':    /* header title for pr */
  401.             strncpy(title, line+1, sizeof(title)-1);
  402.             continue;
  403.  
  404.         case 'L':    /* identification line */
  405.             if (!SH && !HL)
  406.                 banner(line+1, jobname);
  407.             continue;
  408.  
  409.         case '1':    /* troff fonts */
  410.         case '2':
  411.         case '3':
  412.         case '4':
  413.             if (line[1] != '\0')
  414.                 strcpy(fonts[line[0]-'1'], line+1);
  415.             continue;
  416.  
  417.         case 'W':    /* page width */
  418.             strncpy(width+2, line+1, sizeof(width)-3);
  419.             continue;
  420.  
  421.         case 'I':    /* indent amount */
  422.             strncpy(indent+2, line+1, sizeof(indent)-3);
  423.             continue;
  424.  
  425.         default:    /* some file to print */
  426.             i = print(line[0], line+1);
  427.             if (debug)
  428.                 syslog(LOG_ERR, "print(%s)=%d", line, i);
  429.             switch (i) {
  430.             case ERROR:
  431.                 if (bombed == OK)
  432.                     bombed = FATALERR;
  433.                 break;
  434.             case REPRINT:
  435.                 (void) fclose(cfp);
  436.                 return(REPRINT);
  437.             case FILTERERR:
  438.             case ACCESS:
  439.                 bombed = i;
  440.                 sendmail(logname, bombed);
  441.             }
  442.             title[0] = '\0';
  443.             continue;
  444.  
  445.         case 'N':
  446.         case 'U':
  447.         case 'M':
  448.             continue;
  449.         }
  450.     }
  451.     /* pass 2 */
  452.  
  453. pass2:
  454.     fseek(cfp, 0L, 0);
  455.     while (getline(cfp)) {
  456.         switch (line[0]) {
  457.         case 'L':    /* identification line */
  458.             if (!SH && HL)
  459.                 banner(line+1, jobname);
  460.             continue;
  461.  
  462.         case 'M':
  463.             if (bombed < NOACCT)    /* already sent if >= NOACCT */
  464.                 sendmail(line+1, bombed);
  465.             continue;
  466.  
  467.         case 'U':
  468.             (void) unlink(line+1);
  469.         }
  470.     }
  471.     /*
  472.      * clean-up in case another control file exists
  473.      */
  474.     (void) fclose(cfp);
  475.     (void) unlink(file);
  476.     return(bombed == OK ? OK : ERROR);
  477. }
  478.  
  479. /*
  480.  * Print a file.
  481.  * Set up the chain [ PR [ | {IF, OF} ] ] or {IF, RF, TF, NF, DF, CF, VF}.
  482.  * Return -1 if a non-recoverable error occured,
  483.  * 2 if the filter detected some errors (but printed the job anyway),
  484.  * 1 if we should try to reprint this job and
  485.  * 0 if all is well.
  486.  * Note: all filters take stdin as the file, stdout as the printer,
  487.  * stderr as the log file, and must not ignore SIGINT.
  488.  */
  489. print(format, file)
  490.     int format;
  491.     char *file;
  492. {
  493.     register int n;
  494.     register char *prog;
  495.     int fi, fo;
  496.     char *av[15], buf[BUFSIZ];
  497.     int pid, p[2], stopped = 0;
  498.     union wait status;
  499.     struct stat stb;
  500.  
  501.     if (lstat(file, &stb) < 0 || (fi = open(file, O_RDONLY)) < 0) {
  502.         if (debug)
  503.         syslog(LOG_ERR, "can't open %s: %m", file);
  504.         return(ERROR);
  505.     }
  506.  
  507.     if (debug) {
  508.         struct stat statBuf;
  509.  
  510.         if (fstat(fi, &statBuf)) {
  511.         syslog(LOG_ERR, "fstat failed: %m");
  512.         exit(1);
  513.         }
  514.  
  515.         syslog(LOG_ERR, "FI: file=|%s| st_size=%d, st_mode=0x%x",
  516.         file, statBuf.st_size, statBuf.st_mode);
  517.     }
  518.  
  519.     /*
  520.      * Check to see if data file is a symbolic link. If so, it should
  521.      * still point to the same file or someone is trying to print
  522.      * something he shouldn't.
  523.      */
  524.     if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(fi, &stb) == 0 &&
  525.         (stb.st_dev != fdev || stb.st_ino != fino)) {
  526.         if (debug)
  527.             syslog(LOG_ERR, "access denied for %s: %m", file);
  528.         return(ACCESS);
  529.     }
  530.     if (!SF && !tof) {        /* start on a fresh page */
  531.         (void) write(ofd, FF, strlen(FF));
  532.         tof = 1;
  533.     }
  534.     if (IF == NULL && (format == 'f' || format == 'l')) {
  535.         tof = 0;
  536.         while ((n = read(fi, buf, BUFSIZ)) > 0)
  537.             if (write(ofd, buf, n) != n) {
  538.                 (void) close(fi);
  539.                 if (debug)
  540.                     syslog(LOG_ERR, "write err: %m");
  541.                 return(REPRINT);
  542.             }
  543.         (void) close(fi);
  544.         return(OK);
  545.     }
  546.     switch (format) {
  547.     case 'p':    /* print file using 'pr' */
  548.         if (IF == NULL) {    /* use output filter */
  549.             prog = PR;
  550.             av[0] = "pr";
  551.             av[1] = width;
  552.             av[2] = length;
  553.             av[3] = "-h";
  554.             av[4] = *title ? title : " ";
  555.             av[5] = 0;
  556.             fo = ofd;
  557.             goto start;
  558.         }
  559.         pipe(p);
  560.         if ((prchild = dofork(DORETURN)) == 0) {    /* child */
  561.             dup2(fi, 0);        /* file is stdin */
  562.             dup2(p[1], 1);        /* pipe is stdout */
  563.             if (debug) {
  564.                 syslog(LOG_ERR, "execing %s %s, %s, %s, %s, %s",
  565.                   PR, "pr", width, length, "-h", *title?title:"");
  566.             }
  567.             for (n = 3; n < NOFILE; n++)
  568.                 (void) close(n);
  569.             execl(PR, "pr", width, length, "-h",
  570.                 *title ? title : " ", 0);
  571.             syslog(LOG_ERR, "cannot execl %s", PR);
  572.             exit(2);
  573.         }
  574.         (void) close(p[1]);        /* close output side */
  575.         (void) close(fi);
  576.         if (prchild < 0) {
  577.             prchild = 0;
  578.             (void) close(p[0]);
  579.             if (debug)
  580.                 syslog(LOG_ERR, "fork failed: %m");
  581.             return(ERROR);
  582.         }
  583.         fi = p[0];            /* use pipe for input */
  584.     case 'f':    /* print plain text file */
  585.         prog = IF;
  586.         av[1] = width;
  587.         av[2] = length;
  588.         av[3] = indent;
  589.         n = 4;
  590.         break;
  591.     case 'l':    /* like 'f' but pass control characters */
  592.         prog = IF;
  593.         av[1] = "-c";
  594.         av[2] = width;
  595.         av[3] = length;
  596.         av[4] = indent;
  597.         n = 5;
  598.         break;
  599.     case 'r':    /* print a fortran text file */
  600.         prog = RF;
  601.         av[1] = width;
  602.         av[2] = length;
  603.         n = 3;
  604.         break;
  605.     case 't':    /* print troff output */
  606.     case 'n':    /* print ditroff output */
  607.     case 'd':    /* print tex output */
  608.         (void) unlink(".railmag");
  609.         if ((fo = creat(".railmag", FILMOD)) < 0) {
  610.             syslog(LOG_ERR, "%s: cannot create .railmag", printer);
  611.             (void) unlink(".railmag");
  612.         } else {
  613.             for (n = 0; n < 4; n++) {
  614.                 if (fonts[n][0] != '/')
  615.                     (void) write(fo, "/usr/lib/vfont/", 15);
  616.                 (void) write(fo, fonts[n], strlen(fonts[n]));
  617.                 (void) write(fo, "\n", 1);
  618.             }
  619.             (void) close(fo);
  620.         }
  621.         prog = (format == 't') ? TF : (format == 'n') ? NF : DF;
  622.         av[1] = pxwidth;
  623.         av[2] = pxlength;
  624.         n = 3;
  625.         break;
  626.     case 'c':    /* print cifplot output */
  627.         prog = CF;
  628.         av[1] = pxwidth;
  629.         av[2] = pxlength;
  630.         n = 3;
  631.         break;
  632.     case 'g':    /* print plot(1G) output */
  633.         prog = GF;
  634.         av[1] = pxwidth;
  635.         av[2] = pxlength;
  636.         n = 3;
  637.         break;
  638.     case 'v':    /* print raster output */
  639.         prog = VF;
  640.         av[1] = pxwidth;
  641.         av[2] = pxlength;
  642.         n = 3;
  643.         break;
  644.     default:
  645.         (void) close(fi);
  646.         syslog(LOG_ERR, "%s: illegal format character '%c'",
  647.             printer, format);
  648.         return(ERROR);
  649.     }
  650.     if ((av[0] = rindex(prog, '/')) != NULL)
  651.         av[0]++;
  652.     else
  653.         av[0] = prog;
  654.     av[n++] = "-n";
  655.     av[n++] = logname;
  656.     av[n++] = "-h";
  657.     av[n++] = fromhost;
  658.     av[n++] = AF;
  659.     av[n] = 0;
  660.     fo = pfd;
  661.     if (ofilter > 0) {        /* stop output filter */
  662.         write(ofd, "\031\1", 2);
  663.         while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter)
  664.         ;
  665.         if (status.w_stopval == WSTOPPED) {
  666.         stopped++;
  667.         } else {
  668.         if (status.w_retcode == 0) {
  669.             if (debug) {
  670.             extern char *XXXX;
  671.  
  672.             syslog(LOG_ERR,
  673.                 "%s: output filter [0x%x] exited (0), pid = 0x%x",
  674.                 printer, ofilter, pid);
  675.             syslog(LOG_ERR, "reason = %s", XXXX);
  676.             }
  677.  
  678.             kill(ofilter, SIGCONT);     /* just to be sure */
  679.  
  680.             ofilter = 0;
  681.         } else {
  682.             (void) close(fi);
  683.             syslog(LOG_WARNING, "%s: output filter died (%d)",
  684.             printer, status.w_retcode);
  685.             return(REPRINT);
  686.         }
  687.         }
  688.     }
  689. start:
  690.     if ((child = dofork(DORETURN)) == 0) {    /* child */
  691.         if (debug) {
  692.         struct stat statBuf;
  693.  
  694.         if (fstat(fi, &statBuf)) {
  695.             syslog(LOG_ERR, "fstat failed: %m");
  696.             exit(1);
  697.         }
  698.  
  699.         syslog(LOG_ERR, "FI2: file=|%s| st_size=%d, st_mode=0x%x",
  700.             file, statBuf.st_size, statBuf.st_mode);
  701.         }
  702.  
  703.         if (dup2(fi, 0)) {
  704.             syslog(LOG_ERR, "dup2 0 failed: %m");
  705.             exit(1);
  706.         }
  707.         if (dup2(fo, 1)) {
  708.             syslog(LOG_ERR, "dup2 0 failed: %m");
  709.             exit(1);
  710.         }
  711. #ifdef sprite
  712.         /*
  713.          * Divert filter errors to /dev/syslog so users have
  714.          * some idea of what the hell happened to their job.
  715.          */
  716.         n = open("/dev/syslog", O_WRONLY);
  717. #else
  718.         n = open(tempfile, O_WRONLY|O_CREAT|O_TRUNC, 0664);
  719. #endif
  720.         if (n >= 0)
  721.             dup2(n, 2);
  722.         if (debug) {
  723.             struct stat statBuf;
  724.  
  725.             if (fstat(0, &statBuf)) {
  726.             syslog(LOG_ERR, "fstat failed: %m");
  727.             exit(1);
  728.             }
  729.  
  730.             syslog(LOG_ERR, "file=|%s| st_size=%d, st_mode=0x%x",
  731.             file, statBuf.st_size, statBuf.st_mode);
  732.  
  733.             syslog(LOG_ERR, "execing %s", prog);
  734.         }
  735.         for (n = 3; n < NOFILE; n++)
  736.             (void) close(n);
  737.         execv(prog, av);
  738.         syslog(LOG_ERR, "cannot execv %s", prog);
  739.         exit(2);
  740.     }
  741.     (void) close(fi);
  742.     if (child < 0) {
  743.         status.w_retcode = 100;
  744.     } else {
  745.         while ((pid = wait(&status)) > 0 && pid != child)
  746.         ;
  747.     }
  748.     child = 0;
  749.     prchild = 0;
  750.     if (stopped) {        /* restart output filter */
  751.         if (kill(ofilter, SIGCONT) < 0) {
  752.         syslog(LOG_ERR, "cannot restart output filter");
  753.         exit(1);
  754.         }
  755.     }
  756.     tof = 0;
  757.     if (!WIFEXITED(status)) {
  758.         syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)",
  759.         printer, format, status.w_termsig);
  760.         return(ERROR);
  761.     }
  762.     switch (status.w_retcode) {
  763.     case 0:
  764.         tof = 1;
  765.         return(OK);
  766.     case 1:
  767.             if (debug) {
  768.             syslog(LOG_ERR, "%s: daemon filter `%c' wants REPRINT",
  769.             printer, format);
  770.         }
  771.         return(REPRINT);
  772.     default:
  773.         syslog(LOG_WARNING, "%s: Daemon filter '%c' exited (%d)",
  774.             printer, format, status.w_retcode);
  775.     case 2:
  776.             if (debug) {
  777.             syslog(LOG_ERR, "%s: ERROR in daemon filter `%c'",
  778.             printer, format);
  779.         }
  780.         return(ERROR);
  781.     }
  782. }
  783.  
  784. /*
  785.  * Send the daemon control file (cf) and any data files.
  786.  * Return -1 if a non-recoverable error occured, 1 if a recoverable error and
  787.  * 0 if all is well.
  788.  */
  789. sendit(file)
  790.     char *file;
  791. {
  792.     register int i, err = OK;
  793.     char *cp, last[BUFSIZ];
  794.  
  795.     /*
  796.      * open control file
  797.      */
  798.     if ((cfp = fopen(file, "r")) == NULL)
  799.         return(OK);
  800.     /*
  801.      *      read the control file for work to do
  802.      *
  803.      *      file format -- first character in the line is a command
  804.      *      rest of the line is the argument.
  805.      *      commands of interest are:
  806.      *
  807.      *            a-z -- "file name" name of file to print
  808.      *              U -- "unlink" name of file to remove
  809.      *                    (after we print it. (Pass 2 only)).
  810.      */
  811.  
  812.     /*
  813.      * pass 1
  814.      */
  815.     while (getline(cfp)) {
  816.     again:
  817.         if (line[0] == 'S') {
  818.             cp = line+1;
  819.             i = 0;
  820.             while (*cp >= '0' && *cp <= '9')
  821.                 i = i * 10 + (*cp++ - '0');
  822.             fdev = i;
  823.             cp++;
  824.             i = 0;
  825.             while (*cp >= '0' && *cp <= '9')
  826.                 i = i * 10 + (*cp++ - '0');
  827.             fino = i;
  828.             continue;
  829.         }
  830.         if (line[0] >= 'a' && line[0] <= 'z') {
  831.             strcpy(last, line);
  832.             while (i = getline(cfp))
  833.                 if (strcmp(last, line))
  834.                     break;
  835.             switch (sendfile('\3', last+1)) {
  836.             case OK:
  837.                 if (i)
  838.                     goto again;
  839.                 break;
  840.             case REPRINT:
  841.                 (void) fclose(cfp);
  842.                 return(REPRINT);
  843.             case ACCESS:
  844.                 sendmail(logname, ACCESS);
  845.             case ERROR:
  846.                 err = ERROR;
  847.             }
  848.             break;
  849.         }
  850.     }
  851.     if (err == OK && sendfile('\2', file) > 0) {
  852.         (void) fclose(cfp);
  853.         return(REPRINT);
  854.     }
  855.     /*
  856.      * pass 2
  857.      */
  858.     fseek(cfp, 0L, 0);
  859.     while (getline(cfp))
  860.         if (line[0] == 'U')
  861.             (void) unlink(line+1);
  862.     /*
  863.      * clean-up in case another control file exists
  864.      */
  865.     (void) fclose(cfp);
  866.     (void) unlink(file);
  867.     return(err);
  868. }
  869.  
  870. /*
  871.  * Send a data file to the remote machine and spool it.
  872.  * Return positive if we should try resending.
  873.  */
  874. sendfile(type, file)
  875.     char type, *file;
  876. {
  877.     register int f, i, amt;
  878.     struct stat stb;
  879.     char buf[BUFSIZ];
  880.     int sizerr, resp;
  881.  
  882.     if (lstat(file, &stb) < 0 || (f = open(file, O_RDONLY)) < 0)
  883.         return(ERROR);
  884.     /*
  885.      * Check to see if data file is a symbolic link. If so, it should
  886.      * still point to the same file or someone is trying to print something
  887.      * he shouldn't.
  888.      */
  889.     if ((stb.st_mode & S_IFMT) == S_IFLNK && fstat(f, &stb) == 0 &&
  890.         (stb.st_dev != fdev || stb.st_ino != fino))
  891.         return(ACCESS);
  892.     (void) sprintf(buf, "%c%d %s\n", type, stb.st_size, file);
  893.     amt = strlen(buf);
  894.     for (i = 0;  ; i++) {
  895.         if (write(pfd, buf, amt) != amt ||
  896.             (resp = response()) < 0 || resp == '\1') {
  897.             (void) close(f);
  898.             return(REPRINT);
  899.         } else if (resp == '\0')
  900.             break;
  901.         if (i == 0)
  902.             status("no space on remote; waiting for queue to drain");
  903.         if (i == 10)
  904.             syslog(LOG_ALERT, "%s: can't send to %s; queue full",
  905.                 printer, RM);
  906.         sleep(5 * 60);
  907.     }
  908.     if (i)
  909.         status("sending to %s", RM);
  910.     sizerr = 0;
  911.     for (i = 0; i < stb.st_size; i += BUFSIZ) {
  912.         amt = BUFSIZ;
  913.         if (i + amt > stb.st_size)
  914.             amt = stb.st_size - i;
  915.         if (sizerr == 0 && read(f, buf, amt) != amt)
  916.             sizerr = 1;
  917.         if (write(pfd, buf, amt) != amt) {
  918.             (void) close(f);
  919.             return(REPRINT);
  920.         }
  921.     }
  922.     (void) close(f);
  923.     if (sizerr) {
  924.         syslog(LOG_INFO, "%s: %s: changed size", printer, file);
  925.         /* tell recvjob to ignore this file */
  926.         (void) write(pfd, "\1", 1);
  927.         return(ERROR);
  928.     }
  929.     if (write(pfd, "", 1) != 1 || response())
  930.         return(REPRINT);
  931.     return(OK);
  932. }
  933.  
  934. /*
  935.  * Check to make sure there have been no errors and that both programs
  936.  * are in sync with eachother.
  937.  * Return non-zero if the connection was lost.
  938.  */
  939. response()
  940. {
  941.     char resp;
  942.  
  943.     if (read(pfd, &resp, 1) != 1) {
  944.         syslog(LOG_INFO, "%s: lost connection", printer);
  945.         return(-1);
  946.     }
  947.     return(resp);
  948. }
  949.  
  950. /*
  951.  * Banner printing stuff
  952.  */
  953. banner(name1, name2)
  954.     char *name1, *name2;
  955. {
  956.     time_t tvec;
  957.     extern char *ctime();
  958.  
  959.     time(&tvec);
  960.     if (!SF && !tof)
  961.         (void) write(ofd, FF, strlen(FF));
  962.     if (SB) {    /* short banner only */
  963.         if (class[0]) {
  964.             (void) write(ofd, class, strlen(class));
  965.             (void) write(ofd, ":", 1);
  966.         }
  967.         (void) write(ofd, name1, strlen(name1));
  968.         (void) write(ofd, "  Job: ", 7);
  969.         (void) write(ofd, name2, strlen(name2));
  970.         (void) write(ofd, "  Date: ", 8);
  971.         (void) write(ofd, ctime(&tvec), 24);
  972.         (void) write(ofd, "\n", 1);
  973.     } else {    /* normal banner */
  974.         (void) write(ofd, "\n\n\n", 3);
  975.         scan_out(ofd, name1, '\0');
  976.         (void) write(ofd, "\n\n", 2);
  977.         scan_out(ofd, name2, '\0');
  978.         if (class[0]) {
  979.             (void) write(ofd,"\n\n\n",3);
  980.             scan_out(ofd, class, '\0');
  981.         }
  982.         (void) write(ofd, "\n\n\n\n\t\t\t\t\tJob:  ", 15);
  983.         (void) write(ofd, name2, strlen(name2));
  984.         (void) write(ofd, "\n\t\t\t\t\tDate: ", 12);
  985.         (void) write(ofd, ctime(&tvec), 24);
  986.         (void) write(ofd, "\n", 1);
  987.     }
  988.     if (!SF)
  989.         (void) write(ofd, FF, strlen(FF));
  990.     tof = 1;
  991. }
  992.  
  993. char *
  994. scnline(key, p, c)
  995.     register char key, *p;
  996.     char c;
  997. {
  998.     register scnwidth;
  999.  
  1000.     for (scnwidth = WIDTH; --scnwidth;) {
  1001.         key <<= 1;
  1002.         *p++ = key & 0200 ? c : BACKGND;
  1003.     }
  1004.     return (p);
  1005. }
  1006.  
  1007. #define TRC(q)    (((q)-' ')&0177)
  1008.  
  1009. scan_out(scfd, scsp, dlm)
  1010.     int scfd;
  1011.     char *scsp, dlm;
  1012. {
  1013.     register char *strp;
  1014.     register nchrs, j;
  1015.     char outbuf[LINELEN+1], *sp, c, cc;
  1016.     int d, scnhgt;
  1017.     extern char scnkey[][HEIGHT];    /* in lpdchar.c */
  1018.  
  1019.     for (scnhgt = 0; scnhgt++ < HEIGHT+DROP; ) {
  1020.         strp = &outbuf[0];
  1021.         sp = scsp;
  1022.         for (nchrs = 0; ; ) {
  1023.             d = dropit(c = TRC(cc = *sp++));
  1024.             if ((!d && scnhgt > HEIGHT) || (scnhgt <= DROP && d))
  1025.                 for (j = WIDTH; --j;)
  1026.                     *strp++ = BACKGND;
  1027.             else
  1028.                 strp = scnline(scnkey[c][scnhgt-1-d], strp, cc);
  1029.             if (*sp == dlm || *sp == '\0' || nchrs++ >= PW/(WIDTH+1)-1)
  1030.                 break;
  1031.             *strp++ = BACKGND;
  1032.             *strp++ = BACKGND;
  1033.         }
  1034.         while (*--strp == BACKGND && strp >= outbuf)
  1035.             ;
  1036.         strp++;
  1037.         *strp++ = '\n';    
  1038.         (void) write(scfd, outbuf, strp-outbuf);
  1039.     }
  1040. }
  1041.  
  1042. dropit(c)
  1043.     char c;
  1044. {
  1045.     switch(c) {
  1046.  
  1047.     case TRC('_'):
  1048.     case TRC(';'):
  1049.     case TRC(','):
  1050.     case TRC('g'):
  1051.     case TRC('j'):
  1052.     case TRC('p'):
  1053.     case TRC('q'):
  1054.     case TRC('y'):
  1055.         return (DROP);
  1056.  
  1057.     default:
  1058.         return (0);
  1059.     }
  1060. }
  1061.  
  1062. /*
  1063.  * sendmail ---
  1064.  *   tell people about job completion
  1065.  */
  1066. sendmail(user, bombed)
  1067.     char *user;
  1068.     int bombed;
  1069. {
  1070.     register int i;
  1071.     int p[2], s;
  1072.     register char *cp;
  1073.     char buf[100];
  1074.     struct stat stb;
  1075.     FILE *fp;
  1076.  
  1077.     pipe(p);
  1078.     if ((s = dofork(DORETURN)) == 0) {        /* child */
  1079.         dup2(p[0], 0);
  1080.         for (i = 3; i < NOFILE; i++)
  1081.             (void) close(i);
  1082.         if ((cp = rindex(MAIL, '/')) != NULL)
  1083.             cp++;
  1084.         else
  1085.             cp = MAIL;
  1086.         sprintf(buf, "%s@@%s", user, fromhost);
  1087.         execl(MAIL, cp, buf, 0);
  1088.         exit(0);
  1089.     } else if (s > 0) {                /* parent */
  1090.         dup2(p[1], 1);
  1091.         printf("To: %s@@%s\n", user, fromhost);
  1092.         printf("Subject: printer job\n\n");
  1093.         printf("Your printer job ");
  1094.         if (*jobname)
  1095.             printf("(%s) ", jobname);
  1096.         switch (bombed) {
  1097.         case OK:
  1098.             printf("\ncompleted successfully\n");
  1099.             break;
  1100.         default:
  1101.         case FATALERR:
  1102.             printf("\ncould not be printed\n");
  1103.             break;
  1104.         case NOACCT:
  1105.             printf("\ncould not be printed without an account on %s\n", host);
  1106.             break;
  1107.         case FILTERERR:
  1108.             if (stat(tempfile, &stb) < 0 || stb.st_size == 0 ||
  1109.                 (fp = fopen(tempfile, "r")) == NULL) {
  1110.                 printf("\nwas printed but had some errors\n");
  1111.                 break;
  1112.             }
  1113.             printf("\nwas printed but had the following errors:\n");
  1114.             while ((i = getc(fp)) != EOF)
  1115.                 putchar(i);
  1116.             (void) fclose(fp);
  1117.             break;
  1118.         case ACCESS:
  1119.             printf("\nwas not printed because it was not linked to the original file\n");
  1120.         }
  1121.         fflush(stdout);
  1122.         (void) close(1);
  1123.     }
  1124.     (void) close(p[0]);
  1125.     (void) close(p[1]);
  1126.     wait(&s);
  1127. }
  1128.  
  1129. /*
  1130.  * dofork - fork with retries on failure
  1131.  */
  1132. dofork(action)
  1133.     int action;
  1134. {
  1135.     register int i, pid;
  1136.  
  1137.     for (i = 0; i < 20; i++) {
  1138.         if ((pid = fork()) < 0) {
  1139.             sleep((unsigned)(i*i));
  1140.             continue;
  1141.         }
  1142.         /*
  1143.          * Child should run as daemon instead of root
  1144.          */
  1145.         if (pid == 0)
  1146.             setuid(DU);
  1147.         return(pid);
  1148.     }
  1149.     syslog(LOG_ERR, "can't fork");
  1150.  
  1151.     switch (action) {
  1152.     case DORETURN:
  1153.         return (-1);
  1154.     default:
  1155.         syslog(LOG_ERR, "bad action (%d) to dofork", action);
  1156.         /*FALL THRU*/
  1157.     case DOABORT:
  1158.         exit(1);
  1159.     }
  1160.     /*NOTREACHED*/
  1161. }
  1162.  
  1163. /*
  1164.  * Kill child processes to abort current job.
  1165.  */
  1166. abortpr()
  1167. {
  1168.         if (debug)
  1169.         syslog(LOG_ERR, "recieved signal, aborting");
  1170.  
  1171.     (void) unlink(tempfile);
  1172.  
  1173.     kill(0, SIGINT);
  1174.  
  1175.     if (ofilter > 0) {
  1176.         kill(ofilter, SIGCONT);
  1177.         close(ofd);
  1178.     }
  1179.  
  1180.     if (debug)
  1181.         syslog(LOG_ERR, "waiting for children to die");
  1182.  
  1183.     while (wait(0) > 0)
  1184.         ;
  1185.  
  1186.     if (debug)
  1187.         syslog(LOG_ERR, "all children are dead, exiting");
  1188.  
  1189.     exit(0);
  1190. }
  1191.  
  1192. init()
  1193. {
  1194.     int status;
  1195.  
  1196.     if ((status = pgetent(line, printer)) < 0) {
  1197.         syslog(LOG_ERR, "can't open printer description file");
  1198.         exit(1);
  1199.     } else if (status == 0) {
  1200.         syslog(LOG_ERR, "unknown printer: %s", printer);
  1201.         exit(1);
  1202.     }
  1203.     if ((LP = pgetstr("lp", &bp)) == NULL)
  1204.         LP = DEFDEVLP;
  1205.     if ((RP = pgetstr("rp", &bp)) == NULL)
  1206.         RP = DEFLP;
  1207.     if ((LO = pgetstr("lo", &bp)) == NULL)
  1208.         LO = DEFLOCK;
  1209.     if ((ST = pgetstr("st", &bp)) == NULL)
  1210.         ST = DEFSTAT;
  1211.     if ((LF = pgetstr("lf", &bp)) == NULL)
  1212.         LF = DEFLOGF;
  1213.     if ((SD = pgetstr("sd", &bp)) == NULL)
  1214.         SD = DEFSPOOL;
  1215.     if ((DU = pgetnum("du")) < 0)
  1216.         DU = DEFUID;
  1217.     if ((FF = pgetstr("ff", &bp)) == NULL)
  1218.         FF = DEFFF;
  1219.     if ((PW = pgetnum("pw")) < 0)
  1220.         PW = DEFWIDTH;
  1221.     sprintf(&width[2], "%d", PW);
  1222.     if ((PL = pgetnum("pl")) < 0)
  1223.         PL = DEFLENGTH;
  1224.     sprintf(&length[2], "%d", PL);
  1225.     if ((PX = pgetnum("px")) < 0)
  1226.         PX = 0;
  1227.     sprintf(&pxwidth[2], "%d", PX);
  1228.     if ((PY = pgetnum("py")) < 0)
  1229.         PY = 0;
  1230.     sprintf(&pxlength[2], "%d", PY);
  1231.     RM = pgetstr("rm", &bp);
  1232. #ifndef sprite
  1233.     /*
  1234.      * Figure out whether the local machine is the same as the remote 
  1235.      * machine entry (if it exists).  If not, then ignore the local
  1236.      * queue information.
  1237.      */
  1238.      if (RM != (char *) NULL) {
  1239.         char name[256];
  1240.         struct hostent *hp;
  1241.  
  1242.         /* get the standard network name of the local host */
  1243.         gethostname(name, sizeof(name));
  1244.         name[sizeof(name)-1] = '\0';
  1245.         hp = gethostbyname(name);
  1246.         if (hp == (struct hostent *) NULL) {
  1247.             syslog(LOG_ERR,
  1248.             "unable to get network name for local machine %s",
  1249.             name);
  1250.             goto localcheck_done;
  1251.         } else strcpy(name, hp->h_name);
  1252.  
  1253.         /* get the standard network name of RM */
  1254.         hp = gethostbyname(RM);
  1255.         if (hp == (struct hostent *) NULL) {
  1256.             syslog(LOG_ERR,
  1257.             "unable to get hostname for remote machine %s", RM);
  1258.             goto localcheck_done;
  1259.         }
  1260.  
  1261.         /* if printer is not on local machine, ignore LP */
  1262.         if (strcmp(name, hp->h_name) != 0) *LP = '\0';
  1263.     }
  1264. #endif /* sprite */
  1265. localcheck_done:
  1266.  
  1267.     AF = pgetstr("af", &bp);
  1268.     OF = pgetstr("of", &bp);
  1269.     IF = pgetstr("if", &bp);
  1270.     RF = pgetstr("rf", &bp);
  1271.     TF = pgetstr("tf", &bp);
  1272.     NF = pgetstr("nf", &bp);
  1273.     DF = pgetstr("df", &bp);
  1274.     GF = pgetstr("gf", &bp);
  1275.     VF = pgetstr("vf", &bp);
  1276.     CF = pgetstr("cf", &bp);
  1277.     TR = pgetstr("tr", &bp);
  1278.     RS = pgetflag("rs");
  1279.     SF = pgetflag("sf");
  1280.     SH = pgetflag("sh");
  1281.     SB = pgetflag("sb");
  1282.     HL = pgetflag("hl");
  1283.     RW = pgetflag("rw");
  1284.     BR = pgetnum("br");
  1285.     if ((FC = pgetnum("fc")) < 0)
  1286.         FC = 0;
  1287.     if ((FS = pgetnum("fs")) < 0)
  1288.         FS = 0;
  1289.     if ((XC = pgetnum("xc")) < 0)
  1290.         XC = 0;
  1291.     if ((XS = pgetnum("xs")) < 0)
  1292.         XS = 0;
  1293.     tof = !pgetflag("fo");
  1294. }
  1295.  
  1296. /*
  1297.  * Acquire line printer or remote connection.
  1298.  */
  1299. openpr()
  1300. {
  1301.     register int i, n;
  1302.     int resp;
  1303.  
  1304.     if (*LP) {
  1305.         for (i = 1; ; i = i < 32 ? i << 1 : i) {
  1306.             pfd = open(LP, RW ? O_RDWR : O_WRONLY);
  1307.             if (pfd >= 0)
  1308.             break;
  1309. #ifdef sprite
  1310.             if (RM != NULL) {
  1311.                 /*
  1312.                  * If couldn't open the device and a remote host
  1313.                  * is specified for the printer, go use TCP
  1314.                  * for the connection.
  1315.                  */
  1316.                 goto use_remote;
  1317.             }
  1318. #endif
  1319.             if (errno == ENOENT) {
  1320.                 syslog(LOG_ERR, "%s: %m", LP);
  1321.                 exit(1);
  1322.             }
  1323.             if (i == 1)
  1324.                 status("waiting for %s to become ready (offline ?)", printer);
  1325.             sleep(i);
  1326.         }
  1327.         if (isatty(pfd))
  1328.             setty();
  1329.         status("%s is ready and printing", printer);
  1330.     } else if (RM != NULL) {
  1331. use_remote:
  1332.         for (i = 1; ; i = i < 256 ? i << 1 : i) {
  1333.             resp = -1;
  1334.             pfd = getport(RM);
  1335.             if (pfd >= 0) {
  1336.                 (void) sprintf(line, "\2%s\n", RP);
  1337.                 n = strlen(line);
  1338.                 if (write(pfd, line, n) == n &&
  1339.                     (resp = response()) == '\0')
  1340.                     break;
  1341.                 (void) close(pfd);
  1342.             }
  1343.             if (i == 1) {
  1344.                 if (resp < 0)
  1345.                     status("waiting for %s to come up", RM);
  1346.                 else {
  1347.                     status("waiting for queue to be enabled on %s", RM);
  1348.                     i = 256;
  1349.                 }
  1350.             }
  1351.             sleep(i);
  1352.         }
  1353.         status("sending to %s", RM);
  1354.         remote = 1;
  1355.     } else {
  1356.         syslog(LOG_ERR, "%s: no line printer device or host name",
  1357.             printer);
  1358.         exit(1);
  1359.     }
  1360.     /*
  1361.      * Start up an output filter, if needed.
  1362.      */
  1363.     if (OF) {
  1364.         int p[2];
  1365.         char *cp;
  1366.  
  1367.         pipe(p);
  1368.         if ((ofilter = dofork(DOABORT)) == 0) {    /* child */
  1369.             dup2(p[0], 0);        /* pipe is std in */
  1370.             dup2(pfd, 1);        /* printer is std out */
  1371.             if ((cp = rindex(OF, '/')) == NULL)
  1372.                 cp = OF;
  1373.             else
  1374.                 cp++;
  1375.             if (debug) {
  1376.                 syslog(LOG_ERR, "execing %s %s, %d, %d",
  1377.                 OF, cp, width, length);
  1378.             }
  1379.             for (i = 3; i < NOFILE; i++)
  1380.                 (void) close(i);
  1381.             execl(OF, cp, width, length, 0);
  1382.             syslog(LOG_ERR, "%s: %s: %m", printer, OF);
  1383.             exit(1);
  1384.         }
  1385.         (void) close(p[0]);        /* close input side */
  1386.         ofd = p[1];            /* use pipe for output */
  1387.         if (debug) {
  1388.             syslog(LOG_ERR, "ofilter = %x, (%s)", ofilter, OF);
  1389.         }
  1390.     } else {
  1391.         ofd = pfd;
  1392.         ofilter = 0;
  1393.     }
  1394. }
  1395.  
  1396. struct bauds {
  1397.     int    baud;
  1398.     int    speed;
  1399. } bauds[] = {
  1400.     50,    B50,
  1401.     75,    B75,
  1402.     110,    B110,
  1403.     134,    B134,
  1404.     150,    B150,
  1405.     200,    B200,
  1406.     300,    B300,
  1407.     600,    B600,
  1408.     1200,    B1200,
  1409.     1800,    B1800,
  1410.     2400,    B2400,
  1411.     4800,    B4800,
  1412.     9600,    B9600,
  1413.     19200,    EXTA,
  1414.     38400,    EXTB,
  1415.     0,    0
  1416. };
  1417.  
  1418. /*
  1419.  * setup tty lines.
  1420.  */
  1421. setty()
  1422. {
  1423.     struct sgttyb ttybuf;
  1424.     register struct bauds *bp;
  1425. #ifdef sprite
  1426.     int family;
  1427. #endif
  1428.  
  1429. #ifndef sprite
  1430.     if (ioctl(pfd, TIOCEXCL, (char *)0) < 0) {
  1431.         syslog(LOG_ERR, "%s: ioctl(TIOCEXCL): %m", printer);
  1432.         exit(1);
  1433.     }
  1434. #endif
  1435.     if (ioctl(pfd, TIOCGETP, (char *)&ttybuf) < 0) {
  1436.         syslog(LOG_ERR, "%s: ioctl(TIOCGETP): %m", printer);
  1437.         exit(1);
  1438.     }
  1439.     if (BR > 0) {
  1440.         for (bp = bauds; bp->baud; bp++)
  1441.             if (BR == bp->baud)
  1442.                 break;
  1443.         if (!bp->baud) {
  1444.             syslog(LOG_ERR, "%s: illegal baud rate %d", printer, BR);
  1445.             exit(1);
  1446.         }
  1447.         ttybuf.sg_ispeed = ttybuf.sg_ospeed = bp->speed;
  1448.     }
  1449.     ttybuf.sg_flags &= ~FC;
  1450.     ttybuf.sg_flags |= FS;
  1451.     if (ioctl(pfd, TIOCSETP, (char *)&ttybuf) < 0) {
  1452.         syslog(LOG_ERR, "%s: ioctl(TIOCSETP): %m", printer);
  1453.         exit(1);
  1454.     }
  1455.     if (XC || XS) {
  1456.         int ldisc = NTTYDISC;
  1457.  
  1458.         if (ioctl(pfd, TIOCSETD, &ldisc) < 0) {
  1459.             syslog(LOG_ERR, "%s: ioctl(TIOCSETD): %m", printer);
  1460.             exit(1);
  1461.         }
  1462.     }
  1463.     if (XC) {
  1464.         if (ioctl(pfd, TIOCLBIC, &XC) < 0) {
  1465.             syslog(LOG_ERR, "%s: ioctl(TIOCLBIC): %m", printer);
  1466.             exit(1);
  1467.         }
  1468.     }
  1469.     if (XS) {
  1470.         if (ioctl(pfd, TIOCLBIS, &XS) < 0) {
  1471.             syslog(LOG_ERR, "%s: ioctl(TIOCLBIS): %m", printer);
  1472.             exit(1);
  1473.         }
  1474.     }
  1475.  
  1476. #ifdef sprite
  1477.     /*
  1478.      * Need to set the controlling group of the tty so we may manipulate
  1479.      * it.
  1480.      */
  1481.     Proc_GetFamilyID(PROC_MY_PID, &family);
  1482.     Ioc_SetOwner(pfd, family, IOC_OWNER_FAMILY);
  1483. #endif /* sprite */
  1484.  
  1485. }
  1486.  
  1487. /*VARARGS1*/
  1488. status(msg, a1, a2, a3)
  1489.     char *msg;
  1490. {
  1491.     register int fd;
  1492.     char buf[BUFSIZ];
  1493.  
  1494.     umask(0);
  1495.     fd = open(ST, O_WRONLY|O_CREAT, 0664);
  1496.     if (fd < 0 || flock(fd, LOCK_EX) < 0) {
  1497.         syslog(LOG_ERR, "%s: %s: %m", printer, ST);
  1498.         exit(1);
  1499.     }
  1500.     ftruncate(fd, 0);
  1501.     sprintf(buf, msg, a1, a2, a3);
  1502.     strcat(buf, "\n");
  1503.     (void) write(fd, buf, strlen(buf));
  1504.     (void) close(fd);
  1505. }
  1506.  
  1507. @
  1508.  
  1509.  
  1510. 1.4
  1511. log
  1512. @Fixed this so it creates the spool directory if it has to.
  1513. This avoids ugly error messages on fresh file systems and
  1514. when new printers are added.
  1515. @
  1516. text
  1517. @a1425 1
  1518. #ifndef sprite
  1519. a1431 1
  1520. #endif /* sprite */
  1521. @
  1522.  
  1523.  
  1524. 1.3
  1525. log
  1526. @Changed print() so filter error output goes to "/dev/syslog"
  1527. @
  1528. text
  1529. @d83 6
  1530. d90 1
  1531. a90 1
  1532.     if (open(LF, O_WRONLY|O_APPEND, 0664) < 0) {
  1533. a107 2
  1534.         syslog(LOG_ERR, "%s: %m", SD);
  1535.         exit(1);
  1536. @
  1537.  
  1538.  
  1539. 1.2
  1540. log
  1541. @*** empty log message ***
  1542. @
  1543. text
  1544. @d664 7
  1545. d672 1
  1546. @
  1547.  
  1548.  
  1549. 1.1
  1550. log
  1551. @Initial revision
  1552. @
  1553. text
  1554. @d69 1
  1555. d107 1
  1556. a107 1
  1557.     lfd = open(LO, O_WRONLY|O_CREAT, 0644);
  1558. d113 16
  1559. a128 2
  1560.         if (errno == EWOULDBLOCK)    /* active deamon present */
  1561.             exit(0);
  1562. d307 1
  1563. a307 1
  1564.     while (getline(cfp))
  1565. d379 4
  1566. a382 1
  1567.             switch (i = print(line[0], line+1)) {
  1568. d403 1
  1569. a403 1
  1570.  
  1571. d408 1
  1572. a408 1
  1573.     while (getline(cfp))
  1574. d423 1
  1575. d454 18
  1576. a471 2
  1577.     if (lstat(file, &stb) < 0 || (fi = open(file, O_RDONLY)) < 0)
  1578.         return(ERROR);
  1579. d478 3
  1580. a480 1
  1581.         (stb.st_dev != fdev || stb.st_ino != fino))
  1582. d482 1
  1583. d492 2
  1584. d516 4
  1585. d521 3
  1586. a523 2
  1587.                 (void) close(n);
  1588.             execl(PR, "pr", width, length, "-h", *title ? title : " ", 0);
  1589. d532 2
  1590. d615 24
  1591. a638 8
  1592.         write(ofd, "\031\1", 2);
  1593.         while ((pid = wait3(&status, WUNTRACED, 0)) > 0 && pid != ofilter)
  1594.             ;
  1595.         if (status.w_stopval != WSTOPPED) {
  1596.             (void) close(fi);
  1597.             syslog(LOG_WARNING, "%s: output filter died (%d)",
  1598.                 printer, status.w_retcode);
  1599.             return(REPRINT);
  1600. d640 1
  1601. a640 1
  1602.         stopped++;
  1603. d644 20
  1604. a663 2
  1605.         dup2(fi, 0);
  1606.         dup2(fo, 1);
  1607. d667 13
  1608. d681 1
  1609. a681 1
  1610.             (void) close(n);
  1611. d687 6
  1612. a692 5
  1613.     if (child < 0)
  1614.         status.w_retcode = 100;
  1615.     else
  1616.         while ((pid = wait(&status)) > 0 && pid != child)
  1617.             ;
  1618. d696 4
  1619. a699 4
  1620.         if (kill(ofilter, SIGCONT) < 0) {
  1621.             syslog(LOG_ERR, "cannot restart output filter");
  1622.             exit(1);
  1623.         }
  1624. d703 3
  1625. a705 3
  1626.         syslog(LOG_WARNING, "%s: Daemon filter '%c' terminated (%d)",
  1627.             printer, format, status.w_termsig);
  1628.         return(ERROR);
  1629. d712 4
  1630. d721 4
  1631. d1113 3
  1632. d1117 1
  1633. d1119 2
  1634. a1120 1
  1635.     if (ofilter > 0)
  1636. d1122 6
  1637. d1130 4
  1638. d1251 3
  1639. a1253 3
  1640.             pfd = open(LP, RW ? O_RDWR : O_WRONLY);
  1641.             if (pfd >= 0)
  1642.                 break;
  1643. d1263 1
  1644. a1263 1
  1645. #endif /* sprite */
  1646. a1315 2
  1647.             for (i = 3; i < NOFILE; i++)
  1648.                 (void) close(i);
  1649. d1320 6
  1650. d1332 3
  1651. @
  1652.